#ifndef XHTMLTREE_H
#define XHTMLTREE_H

#include "stdafx.h"
#include <afxtempl.h>

extern UINT WM_XHTMLTREE_CHECKBOX_CLICKED;
extern UINT WM_XHTMLTREE_ITEM_EXPANDED;
const int TV_NOIMAGE = 0xFFFE;


//=============================================================================
// CXHtmlTree data
//=============================================================================
struct XHTMLTREEDATA
{
    // ctor
    XHTMLTREEDATA()
    {
        bChecked         = FALSE;
        bEnabled         = TRUE;
        bSeparator       = FALSE;

        // below are reserved for CXHtmlTree use only
        hTreeCtrl        = 0;
        bExpanded        = FALSE;
        bHasBeenExpanded = FALSE;
        nChildren        = 0;
        nChecked         = 0;
        nSeparators      = 0;
        nCount++;
    }

    // dtor
    virtual ~XHTMLTREEDATA()
    {
        nCount--;
    }

    BOOL    bChecked;                // TRUE = item checkbox is checked
    BOOL    bEnabled;                // TRUE = enabled, FALSE = disabled 
                                    // (gray text)
    BOOL    bSeparator;                // TRUE = item is separator; cannot have children

    // below are reserved for CXHtmlTree use only

    HWND    hTreeCtrl;                // HWND of tree control
    BOOL    bExpanded;                // TRUE = item is expanded to show its children
    BOOL    bHasBeenExpanded;        // TRUE = item has been expanded (at least once)
    int        nChildren;                // total count of children of this 
                                    // item
    int        nChecked;                // count of children that are 
                                    // checked - an item in a "mixed" 
                                    // state is counted as being 
                                    // unchecked
    int        nSeparators;            // count of children that are separators
    static int nCount;                // incremented in ctor, decremented in dtor
};

//=============================================================================
// data returned in notification messages
//=============================================================================
struct XHTMLTREEMSGDATA
{
    HWND        hCtrl;                // hwnd of XHtmlTree
    UINT        nCtrlId;            // id of XHtmlTree
    HTREEITEM    hItem;                // current item
};

//=============================================================================
class CXHtmlTree : public CTreeCtrl
//=============================================================================
{
//=============================================================================
// Construction
//=============================================================================
public:
    CXHtmlTree();
    virtual ~CXHtmlTree();

//=============================================================================
// Attributes
//=============================================================================
public:

    enum CheckedState { UNUSED1 = 0, 
                        UNCHECKED, CHECKED, TRISTATE, 
                        UNUSED2,
                        UNCHECKED_DISABLED, CHECKED_DISABLED, TRISTATE_DISABLED };

    COLORREF    GetBkColor() { return m_crCustomWindow; }
    BOOL        GetBit(DWORD bits, DWORD bitmask) { return bits & bitmask; }
    BOOL        GetCheck(HTREEITEM hItem);
    int            GetCheckedCount();
    int            GetChildrenCheckedCount(HTREEITEM hItem);
    int            GetChildrenCount(HTREEITEM hItem);
    int            GetChildrenDisabledCount(HTREEITEM hItem);
    COLORREF    GetDisabledColor(COLORREF color);
    HTREEITEM    GetFirstCheckedItem();
    BOOL        GetHasBeenExpanded(HTREEITEM hItem);
    BOOL        GetHasCheckBoxes() { return m_bCheckBoxes; }
    BOOL        GetImages() { return m_bImages; }
    int            GetIndentLevel(HTREEITEM hItem);
    COLORREF    GetInsertMarkColor() { return m_crInsertMark; }
    CString        GetItemNote(HTREEITEM hItem, BOOL bStripHtml = FALSE);
    COLORREF    GetItemTextBkColor(HTREEITEM hItem);
    COLORREF    GetItemTextColor(HTREEITEM hItem);
    XHTMLTREEDATA * GetItemDataStruct(HTREEITEM hItem);
    CString        GetItemText(HTREEITEM hItem, BOOL bStripHtml = FALSE) const;
    HTREEITEM    GetLastItem(HTREEITEM hItem);
    HTREEITEM    GetNextCheckedItem(HTREEITEM hItem);
    HTREEITEM    GetNextItem(HTREEITEM hItem);
    HTREEITEM    GetNextItem(HTREEITEM hItem, UINT nCode)    
                { return CTreeCtrl::GetNextItem(hItem, nCode); }
    HTREEITEM    GetPrevCheckedItem(HTREEITEM hItem);
    HTREEITEM    GetPrevItem(HTREEITEM hItem);
    BOOL        GetSelectFollowsCheck() { return m_bSelectFollowsCheck; }
    COLORREF    GetSeparatorColor() { return m_crSeparator; }        //+++1.6
    int            GetSeparatorCount(HTREEITEM hItem);
    BOOL        GetSmartCheckBox() { return m_bSmartCheck; }
    int            GetStateImage(HTREEITEM hItem);
    COLORREF    GetTextColor() { return m_crCustomWindowText; }

    BOOL        IsChecked(HTREEITEM hItem) { return GetCheck(hItem); }
    BOOL        IsChildNodeOf(HTREEITEM hitem, HTREEITEM hitemSuspectedParent);
    BOOL        IsEnabled(HTREEITEM hItem);
    BOOL        IsExpanded(HTREEITEM hItem);
    HTREEITEM    IsOverItem(LPPOINT lpPoint = NULL);
    BOOL        IsSelected(HTREEITEM hItem);
    BOOL        IsSeparator(HTREEITEM hItem);

    COLORREF    SetBkColor(COLORREF rgb);
    void        SetBit(DWORD& bits, DWORD bitmask, BOOL value)
                {
                    if (value)
                        bits |= bitmask;
                    else
                        bits &= ~bitmask;
                }
    CXHtmlTree&    SetCheck(HTREEITEM hItem, BOOL fCheck = TRUE);
    CXHtmlTree&    SetCheckChildren(HTREEITEM hItem, BOOL fCheck);
    CXHtmlTree&    SetHasCheckBoxes(BOOL bHasCheckBoxes) 
                { m_bCheckBoxes = bHasCheckBoxes; return *this; }
    CXHtmlTree&    SetImages(BOOL bFlag) 
                { m_bImages = bFlag; return *this; }
    COLORREF    SetInsertMarkColor(COLORREF rgb);
    BOOL        SetItemText(HTREEITEM hItem, LPCTSTR lpszItem);
    COLORREF    SetItemTextBkColor(HTREEITEM hItem, COLORREF rgb);
    COLORREF    SetItemTextColor(HTREEITEM hItem, COLORREF rgb);
    CXHtmlTree&    SetItemStateChildren(HTREEITEM hItem, BOOL fCheck);
    CXHtmlTree&    SetSelectFollowsCheck(BOOL bFlag) 
                { m_bSelectFollowsCheck = bFlag; return *this; }
    CXHtmlTree&    SetSeparatorColor(COLORREF rgb);        //+++1.6
    CXHtmlTree&    SetSmartCheckBox(BOOL bFlag) 
                { m_bSmartCheck = bFlag; return *this; }
    COLORREF    SetTextColor(COLORREF rgb);

//=============================================================================
// Operations
//=============================================================================
public:
    void        CheckAll(BOOL bCheck);
    void        CollapseBranch(HTREEITEM hItem);
    BOOL        CreateCheckboxImages();
    BOOL        DeleteItem(HTREEITEM hItem);
    BOOL        EnableBranch(HTREEITEM hItem, BOOL bEnabled);
    BOOL        EnableItem(HTREEITEM hItem, BOOL bEnabled);
    BOOL        EnableWindow(BOOL bEnable = TRUE);
    BOOL        Expand(HTREEITEM hItem, UINT nCode);
    void        ExpandBranch(HTREEITEM hItem);
    void        ExpandAll();
    void        CollapseAll();
    BOOL        DeleteAllItems();
    virtual HTREEITEM FindItem(CString &sSearch, 
                               BOOL bCaseSensitive = FALSE, 
                               BOOL bDownDir = TRUE,
                               BOOL bWholeWord = FALSE, 
                               BOOL bWrap = TRUE,
                               HTREEITEM hItem = NULL);
    int            IncrementChildren(HTREEITEM hItem, int n = 1);
    int            IncrementSeparators(HTREEITEM hItem, int n = 1);
    CXHtmlTree&    Initialize(BOOL bCheckBoxes = FALSE, BOOL bToolTip = FALSE);
    HTREEITEM    InsertItem(LPTVINSERTSTRUCT lpInsertStruct, XHTMLTREEDATA * pData = NULL);
    HTREEITEM    InsertItem(UINT nMask, LPCTSTR lpszItem, int nImage, 
                    int nSelectedImage, UINT nState, UINT nStateMask, 
                    LPARAM lParam, HTREEITEM hParent, HTREEITEM hInsertAfter);
    HTREEITEM    InsertItem(LPCTSTR lpszItem, HTREEITEM hParent = TVI_ROOT, 
                    HTREEITEM hInsertAfter = TVI_LAST );
    HTREEITEM    InsertItem(LPCTSTR lpszItem, int nImage, int nSelectedImage, 
                    HTREEITEM hParent = TVI_ROOT, 
                    HTREEITEM hInsertAfter = TVI_LAST);
    HTREEITEM    InsertSeparator(HTREEITEM hItem);
    void        RedrawItem(HTREEITEM hItem);
    BOOL        SelectItem(HTREEITEM hItem);

//=============================================================================
// Overrides
//=============================================================================
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CXHtmlTree)
public:
    virtual BOOL PreTranslateMessage(MSG* pMsg);

protected:
    virtual void PreSubclassWindow();
    //}}AFX_VIRTUAL

//=============================================================================
// Implementation
//=============================================================================
protected:
    CMap< HTREEITEM, HTREEITEM, XHTMLTREEDATA *, XHTMLTREEDATA *& > m_DataMap;
                                            // maps HTREEITEM ==> XHTMLTREEDATA
    BOOL            m_bSmartCheck;            // TRUE = Smart Checkboxes enabled
    BOOL            m_bCheckBoxes;            // TRUE = checkboxes enabled
    BOOL            m_bSelectFollowsCheck;    // TRUE = item will be selected, 
                                            // after user clicks on checkbox
    BOOL            m_bImages;                // TRUE = allow images
    BOOL            m_bDestroyingTree;
    BOOL            m_bFirstTime;
    HTREEITEM        m_hHotItem;
    HTREEITEM        m_hPreviousItem;
    HTREEITEM        m_hItemButtonDown;
    HTREEITEM        m_hPreviousDropItem;
    int                m_nPadding;                // horizontal padding in pixels
    int                m_nImageHeight;
    CImageList        m_StateImage;
    COLORREF        m_crCustomWindow;
    COLORREF        m_crCustomWindowText;
    COLORREF        m_crWindow;
    COLORREF        m_crWindowText;
    COLORREF        m_crGrayText;
    COLORREF        m_crHighlight;
    COLORREF        m_crHighlightText;
    COLORREF        m_crInsertMark;
    COLORREF        m_crSeparator;
    void        DeleteBranch(HTREEITEM hItem);

    void        DeleteMap();
    int            DrawItemText(CDC *pDC, HTREEITEM hItem, LPCTSTR lpszText, 
                    COLORREF crText, COLORREF crTextBackground, 
                    COLORREF crBackground, CRect& rect);

    int            DrawSeparator(CDC *pDC, HTREEITEM hItem,
                    COLORREF crText, COLORREF crBackground, CRect& rect);
    int            GetNormalImageWidth(HTREEITEM hItem);
    virtual BOOL IsFindValid(HTREEITEM);
    BOOL        IsLeftButtonUp();
    LRESULT        SendRegisteredMessage(UINT nMessage, HTREEITEM hItem, LPARAM lParam = 0);
    int            SetCheckParent(HTREEITEM hItem, int nCount);
    void        SetColors();
    void        SetHotItem(HTREEITEM hItem, UINT nFlags);


//=============================================================================
// Generated message map functions
//=============================================================================
protected:
    //{{AFX_MSG(CXHtmlTree)
    afx_msg BOOL OnClick(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg BOOL OnDblclk(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg void OnDestroy();
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnSysColorChange();
    afx_msg void OnTimer(UINT nIDEvent);
    //}}AFX_MSG

    afx_msg BOOL OnSelchanged(NMHDR * pNMHDR, LRESULT * pResult);
    afx_msg BOOL OnSelchanging(NMHDR * pNMHDR, LRESULT * pResult);

    DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif //XHTMLTREE_H
